#include "Buffer.h"

Buffer::Buffer() : _buffer(BUFFER_DEFAULT_SIZE),
                   _read_idx(0),
                   _write_idx(0)
{
}

// 1. 获取起始地址
char *Buffer::Begin() const
{
    return (char *)&_buffer[0];
}

// 2. 获取当前写入位置
char *Buffer::WritePosition()
{
    return Begin() + _write_idx;
}

// 3. 获取当前读位置
char *Buffer::ReadPosition()
{
    return Begin() + _read_idx;
}

// 4. 获取缓冲区末尾的空闲空间大小
uint64_t Buffer::TailIdSize()
{
    return _buffer.size() - _write_idx;
}

// 5. 获取头部空间剩余大小
uint64_t Buffer::HeadIdSize()
{
    return _read_idx;
}

// 6. 获取可读数据大小
uint64_t Buffer::ReadAbleSize()
{
    return _write_idx - _read_idx;
}

// 7. 移动读偏移量
void Buffer::MoveReadOffset(uint64_t len)
{
    assert(len <= ReadAbleSize());
    _read_idx += len;
}

// 8. 移动写偏移量
void Buffer::MoveWriteOffset(uint64_t len)
{
    assert(len <= (TailIdSize() + HeadIdSize()));
    _write_idx += len;
}

// 9. 确保可写空间足够
void Buffer::EnsureWriteSpace(uint64_t len)
{
    // 1. 尾部空间足够，不用扩容
    if (TailIdSize() > len)
        return;
    // 2. 尾部空间和头部空间一起是否足够
    if ((TailIdSize() + HeadIdSize()) > len)
    {
        uint64_t rsz = ReadAbleSize();
        std::copy(ReadPosition(), ReadPosition() + rsz, Begin());
        _write_idx = rsz;
        _read_idx = 0;
    }
    //3. 总体空间不够，扩容
    else
    {
        _buffer.resize(_write_idx + len);
    }
}

/*            写操作                      */

// 1. 写入数据
void Buffer::Write(const void *data, uint64_t len)
{
    if (len == 0)
        return;
    // 1. 确保有足够的空间
    EnsureWriteSpace(len);
    // 2. 拷贝数据
    std::copy((char *)data, (char *)data + len, WritePosition());
}
void Buffer::WriteAndPush(const void *data, uint64_t len)
{
    Write(data, len);
    MoveWriteOffset(len);
}

void Buffer::WriteString(const std::string &data)
{
    Write((const void *)data.c_str(), data.size());
}
void Buffer::WriteStringAndPush(const std::string &data)
{
    WriteString(data);
    MoveWriteOffset(data.size());
}

void Buffer::WriteBuffer(Buffer &data)
{
    Write((const void *)data.ReadPosition(), data.ReadAbleSize());
}
void Buffer::WriteBufferAndPush(Buffer &data)
{
    WriteBuffer(data);
    MoveWriteOffset(data.ReadAbleSize());
}

/*                 读操作                                           */

void Buffer::Read(void *buf, uint64_t len)
{
    assert(ReadAbleSize() >= len);
    std::copy(ReadPosition(), ReadPosition() + len, (char *)buf);
}
void Buffer::ReadAndPop(void *buf, uint64_t len)
{
    Read(buf, len);
    MoveReadOffset(len);
}

std::string Buffer::ReadAsString(uint64_t len)
{
    assert(ReadAbleSize() >= len);
    std::string str;
    str.resize(len);
    Read(&str[0], len);
    return str;
}
std::string Buffer::ReadAsStringAndPop(uint64_t len)
{
    std::string str = ReadAsString(len);
    MoveReadOffset(len);
    return str;
}

// 查找回车字符的地址
char *Buffer::FindCRLF()
{
    char *res = (char *)memchr(ReadPosition(), '\n', ReadAbleSize());
    return res;
}

// 获取HTTP协议一行的数据
std::string Buffer::GetLine()
{
    const char *pos = FindCRLF();
    if (pos == NULL)
        return "";
    return ReadAsString(pos - ReadPosition() + 1); // 把/n也读进去
}
std::string Buffer::GetLineAndPop()
{
    std::string str = GetLine();
    MoveReadOffset(str.size());
    return str;
}

// 清空缓冲区
void Buffer::Clear()
{
    _read_idx = 0;
    _write_idx = 0;
}
